﻿using System;
using System.Windows.Forms;
using System.Resources;
using System.IO;
using System.Text;

namespace MousePatcher360
{
    public partial class MP360MAIN : Form
    {
        //Constants for moving the form around the screen.
        const int WM_NCLBUTTONDOWN = 0xA1;
        const int WM_NCHITTEST = 0x84;
        const int HT_CAPTION = 0x2;

        //String for ISO File Location
        public string ISOLocation;

        //Counter for the Process (1 - ISO Loading, 2 - SS Patching, 3 - DMI Patching)
        int ProcCount = 0;

        public MP360MAIN()
        {
            InitializeComponent();
            lblStatusText.Text = "Status:\n Waiting for Target ISO (*.iso)";
            btnRESET.Hide();
        }

        private void userControl1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            Message msg = Message.Create(Handle, WM_NCLBUTTONDOWN, (IntPtr)HT_CAPTION, IntPtr.Zero);
            WndProc(ref msg);
        }

        /// <summary>
        /// Moves the form around by handling the WndProc.
        /// </summary>
        /// <param name="m">Message sent.</param>
        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
            if (m.Msg == WM_NCHITTEST)
                m.Result = (IntPtr)HT_CAPTION;
        }


        //Red button. Closes the form.
        private void pictureBox1_Click(object sender, EventArgs e)
        { Application.Exit(); }

        //Yellow button. Minimises the form.
        private void pictureBox2_Click(object sender, EventArgs e)
        { this.WindowState = FormWindowState.Minimized; }


        private void pnlDragNDrop_DragEnter(object sender, DragEventArgs e)
        {
            //Something's entered the DnDrop Panel! Do we accept it?
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
                e.Effect = DragDropEffects.Move;
            else
                e.Effect = DragDropEffects.None;
        }

        /// <summary>
        /// The Drag and Drop manager.
        /// And the actual patching process.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void pnlDragNDrop_DragDrop(object sender, DragEventArgs e)
        {
            //DRAG N DROP EVENT HANDLER
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                if (ProcCount == 0)
                {
                    TSProgressBar.PerformStep();
                    string[] ISO_FILE = (string[])e.Data.GetData(DataFormats.FileDrop);
                    GETISOFILE(ISO_FILE);
                    TSProgressBar.PerformStep();
                    return;
                }
                if (ProcCount == 1)
                {
                    TSProgressBar.PerformStep();
                    string[] SS_FILE_ARRAY = (string[])e.Data.GetData(DataFormats.FileDrop);
                    GETSSFILE(SS_FILE_ARRAY);
                    TSProgressBar.PerformStep();
                    return;
                }
                if (ProcCount == 2)
                {
                    TSProgressBar.PerformStep();
                    string[] DMI_FILE_ARRAY = (string[])e.Data.GetData(DataFormats.FileDrop);
                    GETDMIFILE(DMI_FILE_ARRAY);
                    TSProgressBar.PerformStep();
                    return;
                }
            }
        }

        private void GETISOFILE(string[] ISO_FILE)
        {
            foreach (string ISOFILE in ISO_FILE)
            {
                FileInfo fileinfo = new FileInfo(ISOFILE);

                bool isISO = (fileinfo.Extension.ToLower() == ".iso");
                bool is000 = (fileinfo.Extension.ToLower() == ".000");
                bool isValid;

                if (isISO == true || is000 == true)
                { isValid = true; }
                else
                { isValid = false; }

                //GET EXTENSION (If not ISO, reject and return)
                if ((isValid == true) && (fileinfo.Length > 5000000000))
                {
                    //Passed the test, up the Process Count and Store string for later.
                    ISOLocation = ISOFILE;
                    FileStream fs = new FileStream(ISOLocation, FileMode.Open);

                    lblStatusText.Text = "Status:\n Waiting for Security Sector File (*.bin)";

                    fs.Close();
                    ProcCount++;
                    TSProgressBar.PerformStep();
                }
                else
                {
                    //Be careful, this loads the Win32 API Messagebox. Not the themed one.
                    MessageBox.Show("File dropped is not a valid ISO file", "Invalid Format", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        private void GETSSFILE(string[] SS_FILE_ARRAY)
        {
            foreach (string SSFILE in SS_FILE_ARRAY)
            {
                FileInfo fileinfo = new FileInfo(SSFILE);
                //Just check the extension to start off with...

                if (fileinfo.Extension.ToLower() == ".bin")
                {
                    //So you say you're a binary file, but we want a 2048 byte file. Are you?
                    if (fileinfo.Length.Equals(2048))
                    {
                        try
                        {

                            //Write the SS Info to buffer.
                            FileStream fs_SS = File.OpenRead(SSFILE);
                            FileStream ISOStream = new FileStream(ISOLocation, FileMode.Open);
                            byte[] arraySS = new byte[2048];
                            fs_SS.Read(arraySS, 0, 2048);
                            fs_SS.Close();

                            //Write the SS Buffer to the ISO
                            BinaryWriter binwSS = new BinaryWriter(ISOStream);
                            binwSS.BaseStream.Position = 0xFD8F800;
                            binwSS.Write(arraySS, 0, 2048);
                            binwSS.Flush(); binwSS.Close(); //Finalise and Close SS Writer. It's inefficient, consider changing.


                            lblStatusText.Text = "Status:\n Waiting for DMI File (*.bin)";

                            //Close ISO FileStream. Another bit of inefficient code. Consider single FStream for ISO file.
                            ISOStream.Close();
                        }
                        catch (System.Exception ex)
                        {
                            MessageBox.Show(ex.Message);
                        }
                        ProcCount++;
                        TSProgressBar.PerformStep();
                    }
                }
            }
        }

        private void GETDMIFILE(string[] DMI_FILE_ARRAY)
        {
            foreach (string DMIFILE in DMI_FILE_ARRAY)
            {
                FileInfo fileinfo = new FileInfo(DMIFILE);

                //Just check the extension to start off with...
                if (fileinfo.Extension.ToLower() == ".bin")
                {
                    //So you say you're a binary file, but we want a 2048 byte file. Are you?
                    if (fileinfo.Length.Equals(2048))
                    {
                        //Write Disk Media Info (DMI) to buffer.
                        FileStream fs_DMI = File.OpenRead(DMIFILE);
                        FileStream ISOStream = new FileStream(ISOLocation, FileMode.Open);
                        byte[] arrayDMI = new byte[2048];
                        fs_DMI.Read(arrayDMI, 0, 2048);
                        fs_DMI.Close();

                        //Write the DMI Buffer to the ISO.
                        BinaryWriter binwDMI = new BinaryWriter(ISOStream);
                        binwDMI.BaseStream.Position = 0xFD8F000;
                        binwDMI.Write(arrayDMI, 0, 2048);
                        binwDMI.Flush(); binwDMI.Close(); //Finalise and Close DMI Writer. It's inefficient, consider changing.

                        lblStatusText.Text = "Status:\n All Good!\n Run through ABGX360 to double-check!";

                        //Close ISO FileStream. Another bit of inefficient code. Consider single FStream for ISO file.
                        ISOStream.Close();
                        ProcCount++;
                        TSProgressBar.PerformStep();

                        //Play Mario sound for completion!
                        Completed();
                        TSProgressBar.PerformStep();

                        //Show reset button, and set code to reset form.
                        btnRESET.Show();


                    }
                    else
                    { MessageBox.Show("File dropped is not a valid DMI file", "Invalid Format", MessageBoxButtons.OK, MessageBoxIcon.Error); }
                }
            }
        }

        private void Completed()
        {
            System.Media.SoundPlayer splayer = new System.Media.SoundPlayer(MousePatcher360.Properties.Resources.Completed);
            splayer.Play();

        }

        private void btnRESET_Click(object sender, EventArgs e)
        {
            Application.Restart();
        }

    }
}
